home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
PC World Komputer 2010 April
/
PCWorld0410.iso
/
pluginy Firefox
/
53142
/
53142.xpi
/
content
/
sorepdisplay.js
< prev
next >
Wrap
Text File
|
2009-12-07
|
13KB
|
347 lines
/*##########################################################################
Copyright 2009 Tim Reid
This file is part of the Stack Overflow Reputation Display extension
for Mozilla Firefox.
Stack Overflow Reputation Display is free software: you can
redistribute it and/or modify it under the terms of the GNU General
Public License as published by the Free Software Foundation, either
version 3 of the License, or (at your option) any later version.
Stack Overflow Reputation Display is distributed in the hope that it
will be useful, but WITHOUT ANY WARRANTY; without even the implied
warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
See the GNU General Public License for more details.
You should have received a copy of the GNU General Public
License along with Stack Overflow Reputation Display. If not,
see <http://www.gnu.org/licenses/>.
##########################################################################*/
var sorepdisplay = {
myid: "sorepdisplay@firefox.twistedlip.org",
global: {
accounts: [],
},
displays: null,
debug: false,
interfaces: {
prefs: Components.classes["@mozilla.org/preferences-service;1"]
.getService(Components.interfaces.nsIPrefService)
.getBranch("extensions.sorepdisplay."),
sound: Components.classes["@mozilla.org/sound;1"]
.createInstance(Components.interfaces.nsISound),
wm: Components.classes["@mozilla.org/appshell/window-mediator;1"]
.getService(Components.interfaces.nsIWindowMediator),
console: Components.classes["@mozilla.org/consoleservice;1"]
.getService(Components.interfaces.nsIConsoleService),
},
observe: function (aSubject, aTopic, aData) {
if (aTopic == "nsPref:changed") {
if (0) {
} else if (aData == "config") {
var newconfig = this.interfaces.prefs.getCharPref("config");
if (newconfig != this.global.currentconfig) {
//################################################################
// See below for why this setTimeout() is needed.
//################################################################
var me = this;
setTimeout(function () {
me.redoconfig(newconfig);
me.global.currentconfig = newconfig;
}, 1);
}
} else if (aData == "response") {
var responsetext = this.interfaces.prefs.getCharPref("response");
for (var i=0; i<this.global.accounts.length; i++)
this.global.accounts[i].handleresponse(responsetext);
} else if (aData == "reputationtextcolor") {
this.reputationtextcolor = this.interfaces.prefs.getCharPref("reputationtextcolor");
this.settextcolors();
} else if (aData == "badgetextcolor") {
this.badgetextcolor = this.interfaces.prefs.getCharPref("badgetextcolor");
this.settextcolors();
} else if (aData == "debug") {
this.debug = this.interfaces.prefs.getBoolPref("debug");
for (var i=0; i<this.global.accounts.length; i++)
this.global.accounts[i].debug = this.debug;
} else {
alert("Change in preference " + aData);
}
} else if (aTopic == "soaccount:scorechanged") {
if (this.debug)
this.interfaces.console.logStringMessage("SORepDisplay handling score change...");
for (var i=0; i<this.displays.length; i++)
if (this.displays[i].account === aSubject)
this.displays[i].updatedetails();
}
},
//##########################################################################
// Why is the setTimeout() needed?
//
// In its absence, when the configuration is changed using the preferences
// dialog, the XMLHttpRequest objects generated during the redoconfig()
// call get cancelled before they can complete. This is probably because
// the observe() method is called by the same thread which is handling the
// dialog interaction, but objects associated with that thread get taken
// down when the dialog closes. Evidence supporting this explanation:
// a delay introduced at *any* point between the XMLHttpRequest send()
// call and the return from the observe() call is sufficient to allow the
// XMLHttpRequest to complete correctly.
//
// The workaround to this problem is to call the redoconfig() method as the
// result of a setTimeout() call. This fixes the problem, probably because
// it allows the XMLHttpRequest to be set up in a different context, and
// therefore not cancelled.
//##########################################################################
doOptions: function () {
if (this.debug)
this.interfaces.console.logStringMessage("SORepDisplay opening configuration dialog...");
window.openDialog("chrome://sorepdisplay/content/options.xul",
"options",
"chrome,modal,centerscreen");
},
launchtab: function (url) {
if (this.debug)
this.interfaces.console.logStringMessage("SORepDisplay opening new tab (" + url + ")...");
var numTabs = gBrowser.browsers.length;
for (var index = 0; index < numTabs; index++)
if (gBrowser.getBrowserAtIndex(index).currentURI.spec == url)
break;
if (index < numTabs) {
gBrowser.selectedTab = gBrowser.tabContainer.childNodes[index];
gBrowser.getBrowserForTab(gBrowser.selectedTab).reload();
} else {
gBrowser.selectedTab = gBrowser.addTab(url);
}
},
configureaccounts: function (config) {
var configparts = config.split(/,/);
var soundbase = "chrome://sorepdisplay/content/audio/";
var sounduris = {
up: soundbase + "31189__acclivity__Triangle1.part.wav",
down: soundbase + "66127__jobro__jobromedia_bullet_slowdown.lq.wav",
};
var accounts = [];
for (var i=0; i<configparts.length; i++) {
if (configparts[i][0] == "#")
continue;
var account = new SOAccount(configparts[i]);
account.sounduris = sounduris;
account.debug = this.debug;
account.launchtimer();
account.addObserver(this);
accounts.push(account);
}
return accounts;
},
removedisplays: function () {
if (!this.displays)
return;
while (this.displays.length > 0) {
var display = this.displays.shift();
display.elements.panel.parentNode.removeChild(display.elements.panel);
display.elements.popupset.parentNode.removeChild(display.elements.popupset);
}
},
adddisplays: function (accounts) {
var displays = [];
var insertpoint = document.getElementById("sorepdisplay-insertpoint");
var insertbefore = insertpoint.nextSibling;
for (var i=0; i<accounts.length; i++) {
var account = accounts[i];
var display = new SODisplay({
account: account,
});
insertpoint.parentNode.insertBefore(display.elements.panel, insertbefore);
insertpoint.parentNode.insertBefore(display.elements.popupset, insertbefore);
display.updatedetails();
var me = this;
display.elements.menuitems.options.addEventListener("command", function (e) { me.doOptions(e); }, true);
display.registeropener(function (url) { me.launchtab(url); } );
displays.push(display);
}
return displays;
},
removeaccounts: function () {
for (var i=0; i<this.global.accounts.length; i++)
this.global.accounts[i].cleartimer();
this.global.accounts = [];
},
redoconfig: function (config) {
this.removeaccounts();
this.global.accounts = this.configureaccounts(config);
this.global.accountswantingpageloads = this.findaccountswantingpageloads();
var instances = this.findinstances();
for (var i=0; i<instances.length; i++) {
instances[i].removedisplays();
instances[i].displays = instances[i].adddisplays(this.global.accounts);
instances[i].initpageloads();
}
},
findinstances: function () {
var instances = [];
var enumerator = this.interfaces.wm.getEnumerator("navigator:browser");
while(enumerator.hasMoreElements()) {
var win = enumerator.getNext();
if (win.sorepdisplay)
instances.push(win.sorepdisplay);
}
return instances;
},
findotherinstances: function () {
var candidates = this.findinstances();
var instances = [];
for (var i=0; i<candidates.length; i++)
if (candidates[i] !== this)
instances.push(candidates[i]);
return instances;
},
pageload: function (e) {
var changed = false;
var candidates = this.global.accountswantingpageloads;
for (var i=0; i<candidates.length; i++)
changed = changed | candidates[i].pageload(e.originalTarget);
if (changed) {
this.global.currentconfig = this.config;
this.interfaces.prefs.setCharPref("config", this.global.currentconfig);
this.global.accountswantingpageloads = this.findaccountswantingpageloads();
var instances = this.findinstances();
for (var i=0; i<instances.length; i++)
instances[i].initpageloads();
}
},
initpageloads: function () {
var appcontent = document.getElementById("appcontent");
if(appcontent) {
var me = this;
if (this.global.accountswantingpageloads.length > 0) {
this.listener = function (e) { me.pageload(e); };
appcontent.addEventListener("DOMContentLoaded",
this.listener,
false);
} else {
appcontent.removeEventListener("DOMContentLoaded",
this.listener,
false);
}
}
},
findaccountswantingpageloads: function () {
var accounts = []
for (var i=0; i<this.global.accounts.length; i++)
if (this.global.accounts[i].wantspageloads())
accounts.push(this.global.accounts[i]);
return accounts;
},
enablesounds: function (b) {
for (var i=0; i<this.global.accounts.length; i++)
this.global.accounts[i].dosounds = b;
var instances = this.findinstances();
for (var i=0; i<instances.length; i++)
for (var j=0; j<instances[i].displays.length; j++)
instances[i].displays[j].dosounds = b;
},
soundmenu: function (e) {
var newvalue = e.target.getAttribute("checked") == "true";
this.interfaces.prefs.setBoolPref("soundeffects", newvalue);
},
get config () {
var configs = [];
for (var i=0; i<this.global.accounts.length; i++)
configs.push(this.global.accounts[i].config);
return configs.join(",");
},
close: function (e) {
for (var i=0; i<this.global.accounts.length; i++)
this.global.accounts[i].removeObserver(this);
},
settextcolors: function () {
if (this.stylesheet) {
for (var i=0; i<this.stylesheet.cssRules.length; i++)
if (this.stylesheet.cssRules[i].type == CSSRule.STYLE_RULE &&
this.stylesheet.cssRules[i].selectorText == ".reputationtextcolor")
this.stylesheet.deleteRule(i);
for (var i=0; i<this.stylesheet.cssRules.length; i++)
if (this.stylesheet.cssRules[i].type == CSSRule.STYLE_RULE &&
this.stylesheet.cssRules[i].selectorText == ".badgetextcolor")
this.stylesheet.deleteRule(i);
this.stylesheet.insertRule(".reputationtextcolor { color: " + this.reputationtextcolor + "; }", 0);
this.stylesheet.insertRule(".badgetextcolor { color: " + this.badgetextcolor + "; }", 0);
}
},
init: function (e) {
this.debug = this.interfaces.prefs.getBoolPref("debug");
this.reputationtextcolor = this.interfaces.prefs.getCharPref("reputationtextcolor");
this.badgetextcolor = this.interfaces.prefs.getCharPref("badgetextcolor");
var instances = this.findotherinstances();
if (instances.length > 0) {
this.global = instances[0].global;
} else {
this.global.currentconfig = this.interfaces.prefs.getCharPref("config");
this.global.accounts = this.configureaccounts(this.global.currentconfig);
this.global.accountswantingpageloads = this.findaccountswantingpageloads();
}
this.removedisplays();
this.displays = this.adddisplays(this.global.accounts);
this.initpageloads();
var me = this;
this.interfaces.prefs.QueryInterface(Components.interfaces.nsIPrefBranch2);
this.interfaces.prefs.addObserver("", this, false);
var stylesheets = document.styleSheets;
for (var i=0; i<stylesheets.length; i++)
if (stylesheets[i].href == "chrome://sorepdisplay/skin/sorepdisplay.css")
this.stylesheet = stylesheets[i];
this.settextcolors();
},
};
window.addEventListener("load", function (e) { sorepdisplay.init(e); }, false);
window.addEventListener("unload", function (e) { sorepdisplay.close(e); }, false);